package com.halfsword.creativecraft.block.custom.machine.blockentity;

import com.halfsword.creativecraft.block.custom.machine.blockentity.modules.ItemHandlerModule;
import com.halfsword.creativecraft.gui.machine.SpaceCollectorMenu;
import com.halfsword.creativecraft.item.ItemLoader;
import com.halfsword.creativecraft.modules.interfaces.IDataSyncFacet;
import com.halfsword.creativecraft.modules.interfaces.IPersistentDataModule;
import com.halfsword.creativecraft.recipe.SpaceCollectorRecipe;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.SimpleContainer;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
import org.jetbrains.annotations.Nullable;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

public class SpaceShardCollectorMachineBlockEntity extends BaseMachineBlockEntity {

    // ================= 常量定义 =================
    public static final int[] INPUT_SLOTS = {0, 1, 2, 3};
    public static final int MAIN_OUTPUT_SLOT = 4;
    public static final int BYPRODUCT_SLOT = 5;
    private static final int SLOT_COUNT = 6;

    // ================= 模块引用 =================
    protected SpaceCollectorRecipeHandlerModule recipeHandlerModule;

    // ================= 构造函数 =================
    public SpaceShardCollectorMachineBlockEntity(BlockPos pos, BlockState state) {
        super(TileEntities.SPACE_SHARD_COLLECTOR_MACHINE_BE.get(), pos, state);
    }

    // ================= 模块初始化 =================
    @Override
    protected void initializeModules() {
        // 初始化物品处理模块
        ItemHandlerModule itemHandlerModule = new ItemHandlerModule(
                "space_collector_item_handler",
                SLOT_COUNT,
                INPUT_SLOTS,
                new int[]{MAIN_OUTPUT_SLOT, BYPRODUCT_SLOT}
        );
        registerModule(itemHandlerModule);

        // 初始化配方处理模块
        recipeHandlerModule = new SpaceCollectorRecipeHandlerModule(
                "space_collector_recipe_handler",
                itemHandlerModule
        );
        registerModule(recipeHandlerModule);
    }

    // ================= 抽象方法实现 =================
    @Override
    protected void updateCurrentRecipe() {
        recipeHandlerModule.updateCurrentRecipe();
    }

    @Override
    protected boolean hasActiveRecipe() {
        return recipeHandlerModule.hasActiveRecipe();
    }

    @Override
    protected void consumeInputs(int units) {
        recipeHandlerModule.consumeInputs(units);
    }

    @Override
    protected ItemStack getMainOutputProduct() {
        return recipeHandlerModule.getMainOutputProduct();
    }

    @Override
    protected ItemStack getByproductOutput() {
        return recipeHandlerModule.getByproductOutput();
    }

    @Override
    protected void onRecipeChanged() {
        recipeHandlerModule.onRecipeChanged();
    }

    // ================= GUI 接口实现 =================
    @Override
    public Component getDisplayName() {
        return Component.translatable("block.creativecraft.space_collector");
    }

    @Nullable
    @Override
    public AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) {
        return new SpaceCollectorMenu(containerId, playerInventory, this, getContainerData());
    }

    // ================= 辅助方法 =================
    public SpaceCollectorRecipeHandlerModule getRecipeHandlerModule() {
        return recipeHandlerModule;
    }

    // ================= 空间收集器专用配方处理模块 =================
    public class SpaceCollectorRecipeHandlerModule implements IDataSyncFacet, IPersistentDataModule {

        private final String moduleId;
        private final ItemHandlerModule itemHandler;
        private SpaceCollectorRecipe currentRecipe;
        private ResourceLocation currentRecipeId;
        private int progress = 0;
        private int maxProgress = 200;
        private int batchSize = 1;
        private boolean dataDirty = false;
        private long lastRecipeCheckTime;

        public SpaceCollectorRecipeHandlerModule(String moduleId, ItemHandlerModule itemHandler) {
            this.moduleId = moduleId;
            this.itemHandler = itemHandler;
        }

        @Override
        public String getModuleId() {
            return moduleId;
        }

        @Override
        public void tick(Level level, BlockPos pos, BlockState state) {
            if (level.isClientSide()) {
                return; // 客户端不处理配方逻辑
            }

            // 定期检查配方
            if (level.getGameTime() - lastRecipeCheckTime > 20) {
                updateCurrentRecipe();
                lastRecipeCheckTime = level.getGameTime();
            }

            // 处理当前配方
            if (hasActiveRecipe()) {
                progress++;

                if (progress >= maxProgress) {
                    craftItem();
                    progress = 0;
                }
            } else {
                // 没有有效配方时重置状态
                resetProgress();
            }
        }

        public void updateCurrentRecipe() {
            if (level == null) return;

            SimpleContainer container = createPositionAwareContainer();
            Optional<SpaceCollectorRecipe> recipe = level.getRecipeManager()
                    .getRecipeFor(SpaceCollectorRecipe.Type.INSTANCE, container, level);

            if (recipe.isPresent()) {
                if (currentRecipe == null || !currentRecipe.getId().equals(recipe.get().getId())) {
                    currentRecipe = recipe.get();
                    maxProgress = currentRecipe.getProcessingTime();
                    progress = 0;
                    batchSize = calculateBatchSize();
                    onRecipeChanged();
                }
            } else {
                currentRecipe = null;
                currentRecipeId = null;
                batchSize = 1;
            }
        }

        public boolean hasActiveRecipe() {
            return currentRecipe != null && hasRecipe(currentRecipe);
        }

        public void consumeInputs(int units) {
            if (currentRecipe == null || level == null) return;

            if (currentRecipe.isShapeless()) {
                // 按材料类型消耗
                Map<Item, Integer> toConsume = new HashMap<>();
                for (Ingredient ingredient : currentRecipe.getIngredients()) {
                    ItemStack[] items = ingredient.getItems();
                    if (items.length > 0) {
                        Item item = items[0].getItem();
                        toConsume.put(item, toConsume.getOrDefault(item, 0) + units);
                    }
                }

                // 跨槽位消耗材料
                for (int slot : INPUT_SLOTS) {
                    ItemStack stack = itemHandler.getStackInSlot(slot);
                    if (stack.isEmpty()) continue;

                    Item item = stack.getItem();
                    if (toConsume.containsKey(item)) {
                        int needed = toConsume.get(item);
                        if (needed <= 0) continue;

                        int toExtract = Math.min(needed, stack.getCount());
                        itemHandler.setStackInSlot(slot, new ItemStack(item, stack.getCount() - toExtract));
                        toConsume.put(item, needed - toExtract);
                    }
                }
            } else {
                // 有序配方按槽位消耗
                for (int i = 0; i < currentRecipe.getIngredients().size(); i++) {
                    if (i >= INPUT_SLOTS.length) break;

                    int slot = INPUT_SLOTS[i];
                    ItemStack stack = itemHandler.getStackInSlot(slot);
                    if (!stack.isEmpty()) {
                        itemHandler.setStackInSlot(slot, new ItemStack(stack.getItem(), stack.getCount() - units));
                    }
                }
            }

            markDataDirty();
        }

        public ItemStack getMainOutputProduct() {
            if (currentRecipe == null || level == null) return ItemStack.EMPTY;

            // 完全依赖配方定义的输出规则
            ItemStack dimensionOutput = currentRecipe.getOutputForDimension(level, worldPosition);
            if (dimensionOutput != null) {
                return dimensionOutput;
            }

            return currentRecipe.getResultItem(level.registryAccess());
        }

        public ItemStack getByproductOutput() {
            return new ItemStack(ItemLoader.FUELSPACE.get());
        }

        public void onRecipeChanged() {
            // 配方变化时的自定义逻辑
            markDataDirty();
        }

        public int getProgress() {
            return progress;
        }

        public void setProgress(int progress) {
            this.progress = progress;
        }

        public int getMaxProgress() {
            return maxProgress;
        }

        public void setMaxProgress(int maxProgress) {
            this.maxProgress = maxProgress;
        }

        public int calculateBatchSize() {
            if (currentRecipe == null || level == null) return 1;

            int maxBatches = Integer.MAX_VALUE;

            if (currentRecipe.isShapeless()) {
                // 统计配方中每种材料的总需求量
                Map<Item, Integer> totalRequired = new HashMap<>();
                for (Ingredient ingredient : currentRecipe.getIngredients()) {
                    ItemStack[] matching = ingredient.getItems();
                    if (matching.length > 0) {
                        Item item = matching[0].getItem();
                        totalRequired.put(item, totalRequired.getOrDefault(item, 0) + 1);
                    }
                }

                // 统计可用材料总数（跨槽位）
                Map<Item, Integer> totalAvailable = new HashMap<>();
                for (int slot : INPUT_SLOTS) {
                    ItemStack stack = itemHandler.getStackInSlot(slot);
                    if (!stack.isEmpty()) {
                        totalAvailable.put(stack.getItem(),
                                totalAvailable.getOrDefault(stack.getItem(), 0) + stack.getCount());
                    }
                }

                // 按材料类型计算最大批次
                for (Map.Entry<Item, Integer> entry : totalRequired.entrySet()) {
                    Item item = entry.getKey();
                    int required = entry.getValue();
                    int available = totalAvailable.getOrDefault(item, 0);

                    if (available < required) {
                        return 0; // 材料不足
                    }
                    maxBatches = Math.min(maxBatches, available / required);
                }
            } else {
                // 有序配方保持原逻辑
                for (int i = 0; i < currentRecipe.getIngredients().size(); i++) {
                    if (i >= INPUT_SLOTS.length) break;

                    int slot = INPUT_SLOTS[i];
                    ItemStack stack = itemHandler.getStackInSlot(slot);
                    if (stack.isEmpty()) {
                        maxBatches = 0;
                        break;
                    }

                    Ingredient ingredient = currentRecipe.getIngredients().get(i);
                    if (ingredient.test(stack)) {
                        int required = getSlotRequirement(slot);
                        maxBatches = Math.min(maxBatches, stack.getCount() / required);
                    } else {
                        maxBatches = 0;
                        break;
                    }
                }
            }

            // 检查输出容量
            ItemStack output = getMainOutputProduct();
            if (output.isEmpty()) return 0;

            int outputLimit = itemHandler.calculateOutputCapacity(output, MAIN_OUTPUT_SLOT);
            maxBatches = Math.min(maxBatches, outputLimit / output.getCount());

            return Math.max(0, maxBatches);
        }

        /**
         * 制作物品
         */
        protected void craftItem() {
            consumeInputs(1);

            // 生成主产品
            ItemStack mainOutput = getMainOutputProduct().copy();
            distributeOutput(mainOutput);

            // 生成副产品（如果有）
            ItemStack byproduct = getByproductOutput().copy();
            if (!byproduct.isEmpty()) {
                distributeOutput(byproduct);
            }
        }

        /**
         * 分发输出物品
         * @param stack 要分发的物品堆栈
         */
        protected void distributeOutput(ItemStack stack) {
            if (stack.isEmpty()) return;

            // 尝试输出槽位
            for (int slot : itemHandler.getOutputSlots()) {
                if (itemHandler.tryInsertItem(stack, slot)) {
                    return;
                }
            }

            // 如果所有输出槽位都满了，处理溢出
            handleOutputOverflow(stack);
        }

        /**
         * 处理输出溢出
         * @param stack 溢出的物品堆栈
         */
        protected void handleOutputOverflow(ItemStack stack) {
            // 默认情况下，物品会丢失
            // 可以重写此方法以添加自定义溢出处理逻辑
        }

        /**
         * 重置进度
         */
        protected void resetProgress() {
            if (progress > 0) {
                progress = 0;
            }
        }

        // ================= 辅助方法 =================
        private boolean hasRecipe(SpaceCollectorRecipe recipe) {
            if (level == null) return false;

            // 1. 检查输入槽是否满足配方要求
            if (!recipe.matches(createPositionAwareContainer(), level)) {
                return false;
            }

            // 2. 检查输出槽容量
            return itemHandler.canInsertItem(getMainOutputProduct(), MAIN_OUTPUT_SLOT) &&
                    itemHandler.canInsertItem(getByproductOutput(), BYPRODUCT_SLOT);
        }

        private int getSlotRequirement(int slot) {
            return 1; // 有序配方中每个槽位固定消耗1个
        }

        private SimpleContainer createPositionAwareContainer() {
            return new PositionAwareContainer(worldPosition,
                    itemHandler.getStackInSlot(0),
                    itemHandler.getStackInSlot(1),
                    itemHandler.getStackInSlot(2),
                    itemHandler.getStackInSlot(3)
            );
        }

        // ================= 数据同步接口实现 =================
        @Override
        public void populateContainerData(com.halfsword.creativecraft.utils.ContainerDataBuilder builder) {
            builder.addReadOnlyField(this::getProgress)
                    .addReadOnlyField(this::getMaxProgress)
                    .addReadOnlyField(() -> currentRecipe != null ? 1 : 0)
                    .addReadOnlyField(this::calculateBatchSize);
        }

        @Override
        public void readFromContainerData(com.halfsword.creativecraft.utils.ContainerDataReader reader) {
            // 客户端数据读取
            int progress = reader.readInt();
            int maxProgress = reader.readInt();
            int hasRecipe = reader.readInt();
            int batchSize = reader.readInt();

            // 更新客户端显示
            setProgress(progress);
            setMaxProgress(maxProgress);
            // 注意：currentRecipe 和 batchSize 在客户端是只读的
        }

        @Override
        public int getDataFieldCount() {
            return 4; // progress, maxProgress, hasRecipe, batchSize
        }

        @Override
        public void markDataDirty() {
            dataDirty = true;
        }

        @Override
        public boolean isDataDirty() {
            return dataDirty;
        }

        @Override
        public void clearDataDirty() {
            dataDirty = false;
        }

        // ================= 持久化接口实现 =================
        @Override
        public void saveToNBT(CompoundTag tag) {
            if (currentRecipe != null) {
                tag.putString("CurrentRecipe", currentRecipe.getId().toString());
            }
            tag.putInt("Progress", getProgress());
            tag.putInt("MaxProgress", getMaxProgress());
            tag.putInt("BatchSize", batchSize);
        }

        @Override
        public void loadFromNBT(CompoundTag tag) {
            if (tag.contains("CurrentRecipe")) {
                currentRecipeId = ResourceLocation.parse(tag.getString("CurrentRecipe"));
            }
            if (tag.contains("Progress")) {
                setProgress(tag.getInt("Progress"));
            }
            if (tag.contains("MaxProgress")) {
                setMaxProgress(tag.getInt("MaxProgress"));
            }
            if (tag.contains("BatchSize")) {
                batchSize = tag.getInt("BatchSize");
            }
        }

        @Override
        public String getDataKey() {
            return "space_collector_recipe_handler";
        }

        @Override
        public boolean isEmpty() {
            return currentRecipe == null && getProgress() == 0;
        }

        @Override
        public void reset() {
            currentRecipe = null;
            currentRecipeId = null;
            setProgress(0);
            setMaxProgress(200);
            batchSize = 1;
            markDataDirty();
        }

        public void tick() {
            // 在tick中尝试加载配方
            if (currentRecipeId != null && currentRecipe == null && level != null) {
                level.getRecipeManager().byKey(currentRecipeId).ifPresent(recipe -> {
                    if (recipe instanceof SpaceCollectorRecipe) {
                        currentRecipe = (SpaceCollectorRecipe) recipe;
                        currentRecipeId = null; // 清除ID，避免重复加载
                        markDataDirty();
                    }
                });
            }
        }
    }

    // ================= 位置感知容器 =================
    private static class PositionAwareContainer extends SimpleContainer
            implements SpaceCollectorRecipe.PositionalContainer {

        private final BlockPos position;

        public PositionAwareContainer(BlockPos pos, ItemStack... items) {
            super(items);
            this.position = pos;
        }

        @Override
        public BlockPos getPosition() {
            return position;
        }
    }
}